/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package hirt;

import java.awt.Point;
import java.nio.ByteBuffer;
import java.util.Vector;

/**
 * This class is full of utility methods used to translate data to and from
 * bytes so they can be transfer over the network
 * It also contains functions used to translate data to and from Save Strings
 * @author zmiller
 */
public class ByteChanger
{

    /**
     * Returns the passed integer as a byte
     * @param integer
     * @return byte form of integer
     */
    public static byte intToByte(int integer)
    {
        byte content = (byte)integer;
        return content;
    }

    /**
     * Returns the passed string as a byte
     * @param string
     * @return byte form of string
     */
    public static byte[] stringToByte(String string)
    {
        return string.getBytes();
    }

    /**
     * Returns the passed double as a byte
     * @param Double
     * @return byte form of Double
     */
    public static byte doubleToByte(double Double)
    {
        byte content = (byte)Double;
        return content;
    }

    /**
     * Returns the id of the passed Item
     * Return -1 if item is null
     * @param item
     * @return item id
     */
    public static int itemToByte(Item item)
    {
        if (item == null)
        {
            return -1;
        }
        else
        {
            return item.getId();
        }
    }


    /*public static byte[] actionToByte(Action action)
    {
        byte[] buf = new byte[3];
        if (action.getActor() != null)
            buf[0] = intToByte(action.getActor().getId());
        else
            buf[0] = 0;
        buf[1] = doubleToByte(action.getStartTime());
        buf[2] = doubleToByte(action.getDurationTime());
        return buf;

    }

    public static byte[] communicationActionToByte(CommunicationAction action)
    {

        byte[] tmp = actionToByte(action);
        byte[] str = new byte[256];
        str = stringToByte(action.getMessage());
        byte[] buf = append(tmp, str);
        return buf;
    }

    public static byte[] append(byte[] bit1,byte[] bit2)
    {
	byte[] buf = new byte[bit1.length+bit2.length];
	int i;
	for(i=0; i<bit1.length;i++)
	{
		buf[i] = bit1[i];
	}
	for(int j = 0; j < bit2.length; j++)
	{
		buf[j+i] = bit2[j];
	}
	return buf;
    }*/

    /**
     * Returns a section of the passed ByteBuffer
     * Result starts at offset and is of length length
     * Throws exception if buffer is null or subsection passes the end of the buffer
     * @param buffer the is subdivided
     * @param offset of section
     * @param length of section
     * @return subsection of buffer
     * @throws Exception
     */
    public static ByteBuffer wrap(ByteBuffer buf, int offset, int length) throws Exception
    {
        if (buf == null)
        {
            throw new NullPointerException("buffer is null");
        }
        if ((offset + length) > buf.limit())
        {
            throw new Exception("not enought space in given ByteBuffer");
        }
        ByteBuffer result = ByteBuffer.allocate(length);
        byte[] array = buf.array();
        for (int i = 0; i < length; i++)
        {
            result.put(array[i+offset]);
        }
        return result;
    }

    /**
     * Returns a ByteBuffer that contions the value of the passed point
     * @param point
     * @return ByteBuffer containing point
     */
    public static byte[] pointToByte(Point point)
    {
        ByteBuffer buf =ByteBuffer.allocate(8);
        if (point != null)
        {
            buf.putInt(point.x);
            buf.putInt(point.y);
        }
        else
        {
            buf.putInt(Integer.MAX_VALUE);
            buf.putInt(Integer.MAX_VALUE);
        }
        return buf.array();
    }

    /**
     * Returns a ByteBuffer that contatins the passed boolean
     * @param bool
     * @return ByteBuffer contatining bool
     */
    public static byte[] booleanToByte(boolean bool)
    {
        ByteBuffer buf =ByteBuffer.allocate(1);
        byte result;
        if (bool)
            result = 1;
        else
            result = 0;
        buf.put(result);
        return buf.array();
    }

    /**
     * Returns a boolean value based on the passed byte
     * Returns true if passed byte equals 1
     * @param bool
     * @return boolean
     */
    public static boolean getBoolean(byte bool)
    {
        return bool == 1;
    }

    /**
     * Returns the boolean value found in the passed Bytebuffer at the passed index
     * Booleans take up 1 byte in the buffers array
     * @param buf
     * @param index
     * @return boolean
     */
     public static boolean getBoolean(ByteBuffer buf, int index)
    {
        return getBoolean(buf.get(index));
    }

     /**
      * Returns the point found in the passed Bytebuffer at the passed index
      * Points take up 8 bytes in the buffers array
      * @param buf
      * @param index
      * @return
      */
    public static Point getPoint(ByteBuffer buf, int index)
    {
        int resultX = buf.getInt(index);
        int resultY = buf.getInt(index+4);
        if (resultX == Integer.MAX_VALUE && resultY == Integer.MAX_VALUE)
            return null;
        else
            return new Point(resultX,resultY);
    }

    /**
     * Returns the string in the passed Bytebuffer at the passed index of the passed length
     * The String will take up length bytes in the buffers array
     * @param bytes
     * @param index
     * @param length
     * @return
     */
    public static String getString(ByteBuffer bytes, int index, int length)
    {
        String result;
        try
        {
            ByteBuffer buf = null;
            buf = ByteChanger.wrap(bytes, index, bytes.limit()-index);
            result = new String(buf.array(),0,length);
        }
        catch (Exception ex)
        {
            System.out.println("Error makeing communique:  " + ex.getMessage());
            result = "";
        }
        return result;
    }

    /**
     * Returns the Item in the passed Bytebuffer at the passed index of the passed length
     * The Item will take up 4 bytes in the buffers array
     * @param bytes
     * @param items
     * @param byteIndex
     * @return
     */
    public static Item getItem(ByteBuffer bytes, Vector<Item> items, int byteIndex)
    {
        int index = bytes.getInt(byteIndex);  //ID of the item in the buffer
        Item actor;

            if (index >= 0)
                actor = items.get(index);   //ID is the equivalent of index in the passed list
            else
                actor = null;
        return actor;
    }

    /**
     * Returns a subsection of the passed ByteBuffer starting at offset and
     * going until the end of the ByteBuffer
     * @param bytes
     * @param offset
     * @return subsection of bytes
     * @throws Exception
     */
    public static ByteBuffer truncate(ByteBuffer bytes, int offset) throws Exception
    {
        return ByteChanger.wrap(bytes, offset, bytes.limit() - offset);
    }

    /**
     * Returns the string in the passed Bytebuffer at the passed index
     * @param bytes
     * @param index
     * @return
     */
    static String getString(ByteBuffer bytes, int index) {
        int length = bytes.getInt(index);
        return getString(bytes, index+4, length);
    }

    /**
     * This is used with save strings
     * it increments the save string to the next value with in the string
     * @param saveText
     * @return
     */
    public static String incrementString(String saveText)
    {
        int index = saveText.indexOf("\t");
        saveText = saveText.substring(index+1);
        return saveText;
    }

    /**
     * This is used with save strings
     * it gets the next values in the save string
     * @param saveText
     * @return
     */
    public static String getNextValue(String saveText)
    {
        int index = saveText.indexOf("\t");
        String substring = saveText.substring(0, index);
        return substring;
    }

    /**
     * Returns the Item in the passed string
     * the passed string must translate into the items integer ID
     * @param substring
     * @param items
     * @return
     */
    static Item getItem(String substring, Vector<Item> items) {
        int index = Integer.parseInt(substring);        //the ID of the Item
        if (index >= 0 )
            return items.get(index);                // The ID corresponds to its index in the itemlist
        else
            return null;
    }
}
